import XLSX from 'xlsx'

/**
 * 将表格数据转换成excel所需要的数据类型
 * @param thead
 * @param tbody
 * @returns
 */
// a1 = 123 类似于这样定义后，就在会我们输出的excel里的第一行第一列展示123
function handlerXlsxData(thead: any, tbody: any) {
  // 这里必须复制一个thead出来，避免这边的内容变化造成页面无法正常渲染
  thead = thead.map((item: any, index: number) => ({
    title: item.title,
    // 计算表头列号，比如:
    // 第一列：String.fromCharCode(65 + 0) === 'A'
    // 第二列：String.fromCharCode(65 + 1) === 'B'
    col: String.fromCharCode(65 + index),
    key: item.dataIndex,
  }))

  // 数据转换为对象
  const output = tbody.reduce(
    (prev: any, item: any, index: number) =>
      thead.reduce((prev: any, head: any) => {
        // 第一次需要添加表头数据
        if (index === 0) {
          // 列号+行号
          prev[head.col + 1] = { v: head.title }
        }
        // 数据的行号: 1的位置已经给了表头
        prev[head.col + (index + 2)] = { v: item[head.key] }
        return prev
      }, prev),
    {}
  )
  // 获取所有单元格的位置描述[A1...I11]
  const outputPos = Object.keys(output)
  // 计算出范围, excel的第一格和最后一格，比如A1:I11
  output['!ref'] = `${outputPos[0]}:${outputPos.slice(-1)}`
  // 如果需要，可以配置表格列的宽度
  output['!cols'] = [
    { wpx: 45 },
    { wpx: 100 },
    { wpx: 200 },
    { wpx: 80 },
    { wpx: 150 },
    { wpx: 100 },
    { wpx: 300 },
    { wpx: 300 },
  ]
  return output
}

/**
 * 导出excel
 * @param {*} thead 表头数据
 * @param {*} tbody  表格数据
 * @param {*} fileName 需要导出的文件名
 */
export default function ExportXlsx(
  // thead 页面中传过来的columns
  thead: any,
  // tbody 表格的数据
  tbody: any,
  fileName = 'demo.xlsx',
  sheetName = 'sheet 1'
) {
  // 校验参数错误
  if (!thead || !tbody) {
    throw new Error('文件导出数据缺失，请检查调用传参是否正确')
  }

  // 创建并导出excel文件
  // writeFile 表示将对应的数据写入文件流
  XLSX.writeFile(
    {
      // 分表名称
      SheetNames: [sheetName],
      Sheets: {
        sheetName: handlerXlsxData(thead, tbody),
      },
    },
    fileName
  )
}
